Semantik Web  •  Hafta 09

OWL API — II & Reasoner'lar

Çıkarım kuramı, HermiT · Pellet · JFact · ELK, SWRL motorları ve alerji ontolojisinde risk çıkarımı

Lisansüstü Semantik Web Dersi  •  CMPE 583

Hafta 09  •  Kazanımlar

Bu hafta sonunda

  • Reasoner'ın üç temel görevini ve nasıl çalıştığını açıklayabileceksiniz.
  • HermiT, Pellet/Openllet, JFact ve ELK arasında bilinçli seçim yapabileceksiniz.
  • OWLReasoner arayüzünü kısa kod parçalarıyla kullanabileceksiniz.
  • SWRL motoru ile DL reasoner'ın iş bölümünü kurabileceksiniz.
  • Çıkarımı kalıcı hâle getirip tutarsızlığı gerekçesiyle bulabileceksiniz.

01

Ödev 8'in Çözümü

EAN_00005'in kodla eklenmesi.

Çözüm 8.1 — Doğru metot adları

getOWLClassAssertionAxiom( cls("Product"), ind("EAN_00005")); getOWLObjectPropertyAssertionAxiom( op("Contain"), ind("EAN_00005"), ind("Whey_Protein")); getOWLObjectPropertyAssertionAxiom( op("Triggers"), ind("Whey_Protein"), ind("Lactose"));
  • 5 aksiyom: 1 tip + 2 Contain + 2 Triggers.
  • S6 tetiklenir: TC_001 (Lactose) ve TC_004 (Gluten) bu ürünü seçerse.
  • Declaration gerekmez: assertion varlığı ima eder.

02

Çıkarım Nedir?

Reasoner ne yapar, nasıl yapar, neyi garanti eder.

Mantıksal sonuç (entailment)

Bir ontoloji O, bir aksiyom A'yı gerektirir (O ⊨ A) demek: O'yu doğru kılan her yorumda A da doğrudur.

Verili: Adult ⊑ Person Adult(TC_001) Sonuc: Person(TC_001)

Reasoner "olası" değil, zorunlu sonuçları üretir. Bu yüzden çıkarım güvenilirdir: kaynak veri doğruysa sonuç da doğrudur.

Reasoner'ın üç görevi

GörevSoruAlerji ontolojisinde
TutarlılıkOntoloji çelişkili mi?Bir birey hem Person hem Product mu?
SınıflandırmaHangi sınıf hangisinin altında?RiskyProduct ⊑ Product
GerçeklemeHer birey hangi sınıfların üyesi?TC_001 → PersonAtRisk, Adult
isConsistent()
getSubClasses()
getInstances()

Nasıl çalışır? Tableau yöntemi

  • Reasoner doğrudan "kanıtlamaz"; çelişki arar.
  • "TC_001 riskli değil" varsayımı eklenir; model kurulmaya çalışılır.
  • Model kurulamıyorsa varsayım yanlıştır → TC_001 risklidir.
  • Bu yönteme refutation (çürütme) denir; SAT çözücülerdeki mantığın aynısı.
Sonuç: OWL 2 DL için karar verilebilir ama en kötü durumda 2-NEXPTIME. Pratikte optimizasyonlar sayesinde binlerce bireyde saniyeler sürer.

DL reasoner ile kural motoru

BoyutDL reasoner (HermiT)Kural motoru (Drools)
YöntemTableau, çelişki aramaİleri zincirleme, eşleme
DünyaAçık (OWA)Kural gövdesi eşleşirse tetikler
AritmetikYokBuilt-in ile var
Sonuç neredeBellekte, geçiciOntolojiye yazılabilir
Anonim bireyGörürGörmez (DL-safe)

Projede ikisi sırayla çalışır: SWRL hesaplar ve zincirler, HermiT sınıflandırır ve denetler.

03

Reasoner Ailesi

HermiT, Pellet/Openllet, JFact, ELK, FaCT++ ve kural tabanlı yaklaşımlar.

Hangi reasoner, ne için?

ReasonerYöntem / profilGüçlü yanıProjede
HermiTHypertableau, OWL 2 DLKarmaşık kısıtlarda hızlıVarsayılan
Pellet / OpenlletTableau, OWL 2 DLSWRL desteği, açıklamaAlternatif
JFactFaCT++ Java portuSaf Java, kararlıYedek
ELKKural tabanlı, OWL 2 ELÇok büyük taksonomiUygun değil
FaCT++C++ , OWL 2 DLHızYerel kütüphane gerekir

Alerji ontolojisi only, sayı kısıtı ve ayrıklık kullandığı için DL profilindedir — ELK bu kısıtları göz ardı eder.

HermiT ile Pellet arasındaki seçim

HermiT 1.4.5

  • Hypertableau: daha az dallanma
  • Sayı kısıtlarında güçlü
  • SWRL'i doğrudan yürütmez
  • Aktif bakımda

Pellet / Openllet 2.6

  • SWRL kurallarını kendi işler
  • Açıklama (explanation) üretir
  • SPARQL-DL desteği
  • Pellet arşivde; Openllet sürdürülüyor

Projede HermiT + SWRLAPI/Drools ikilisini seçtik: kural yürütme ile DL çıkarımını ayırmak, hangi sonucun nereden geldiğini izlenebilir kılıyor.

Kural tabanlı yaklaşımlar: ROWL ve akrabaları

AraçNe yaparAlerji projesinde kullanımı
ROWLProtégé eklentisi: SWRL kuralını OWL aksiyomlarına çevirirS3 gibi kuralları kısıt olarak yazıp saf DL çıkarımı almak
SWRLAPI + DroolsKuralı üretim kuralına çevirip yürütürProjenin ana yolu; aritmetik için zorunlu
OWL 2 RL / RDFoxMateryalizasyon, ölçekliMilyonlarca ürün senaryosu
SPIN / SHACL RulesSPARQL tabanlı kuralRDF yığını üzerinde alternatif

ROWL'un sınırı: aritmetik ve built-in çeviremez. S4 (BMI) kuralı OWL'a çevrilemez — bu yüzden kural motoru vazgeçilmezdir.

ROWL: kuraldan aksiyoma çeviri

SWRL kuralı

Product(?u) ^ Contain(?u, ?f) ^ Triggers(?f, ?al) -> RiskyProduct(?u)

ROWL çıktısı (OWL kısıtı)

Product and (Contain some (Triggers some Allergy)) SubClassOf RiskyProduct

Kazanç: kural motoru gerekmez, HermiT tek başına çıkarır. Kayıp: hangi katkının suçlu olduğu bilgisi üretilemez — S6'nın Effected_Allergen çıktısı kaybolur.

04

OWLReasoner Arayüzü

Kısa kod parçalarıyla, adım adım.

Adım 1 — Reasoner'ı oluştur

OWLReasonerFactory rf = new ReasonerFactory(); // HermiT OWLReasoner r = rf.createReasoner(ont);
  • Tek arayüz, çok motor: OWLReasoner.
  • Motoru değiştirmek için yalnızca fabrika satırı değişir.
  • Reasoner ontolojinin o anki hâlini alır.
HermiT : new org.semanticweb.HermiT.ReasonerFactory() Openllet: new openllet.owlapi.OpenlletReasonerFactory() JFact : new uk.ac.manchester.cs.jfact.JFactFactory() ELK : new org.semanticweb.elk.owlapi.ElkReasonerFactory()

Adım 2 — Tutarlılık denetimi

if (!r.isConsistent()) { System.out.println("TUTARSIZ!"); return; } // Tatmin edilemeyen siniflar r.getUnsatisfiableClasses() .getEntitiesMinusBottom() .forEach(System.out::println);
  • Tutarsız ontolojide her şey doğrudur — sorgular anlamsızlaşır.
  • Bu yüzden her zaman ilk bu denetim yapılır.
  • Unsatisfiable sınıf: üyesi hiç olamayan sınıf. Genelde model hatasıdır.

Adım 3 — Sınıflandırma

OWLClass person = cls("Person"); // Dogrudan alt siniflar r.getSubClasses(person, true) .getFlattened().forEach(System.out::println); // Tum ust siniflar r.getSuperClasses(cls("PersonAtRisk"), false) .getFlattened().forEach(System.out::println);
  • true = yalnızca doğrudan, false = tüm hiyerarşi.
  • Dönen tip NodeSet: eşdeğer sınıflar aynı düğümde gruplanır.
  • getFlattened() ile düz kümeye çevrilir.
Adult  · PersonAtRisk  · LactoseIntolerantPerson (çıkarıldı)

Adım 4 — Gerçekleme: birey ↔ sınıf

Sınıfın üyeleri

r.getInstances( cls("PersonAtRisk"), false) .getFlattened() .forEach(System.out::println);

Bireyin tipleri

r.getTypes( ind("TC_001"), false) .getFlattened() .forEach(System.out::println);
getInstances → TC_001 TC_002 TC_003 TC_004 getTypes → Person, Adult, PersonAtRisk, LactoseIntolerantPerson

Adım 5 — Çıkarılan ilişki değerleri

// Cikarilan nesne ozelligi degerleri r.getObjectPropertyValues( ind("TC_001"), op("Effected_Allergen")) .getFlattened().forEach(System.out::println); // Cikarilan veri ozelligi degerleri r.getDataPropertyValues( ind("TC_001"), dp("hasBMI")) .forEach(l -> System.out.println(l.getLiteral()));
  • Kritik ayrım: EntitySearcher yalnızca bildirilmişi okur; reasoner çıkarılanı da verir.
  • Alt özellik hiyerarşisi burada devreye girer: Lactose_Allergen değerleri üst özellikte de görünür.

Adım 6 — Belirli bir sonucu test et

OWLAxiom soru = df.getOWLClassAssertionAxiom( cls("PersonAtRisk"), ind("TC_001")); System.out.println(r.isEntailed(soru)); // true // Sinif iliskisi testi System.out.println(r.isEntailed( df.getOWLSubClassOfAxiom( cls("RiskyProduct"), cls("Product"))));
  • Bütün çıkarımı listelemek yerine tek soruyu sormak çok daha hızlıdır.
  • Birim testleri için ideal: beklenen çıkarımı JUnit ile doğrulayın.
  • false dönmesi "yanlış" değil, "gerektirilmiyor" demektir (OWA).

Aynı kod, üç farklı motor

void rapor(OWLReasonerFactory rf, String ad) { long t0 = System.currentTimeMillis(); OWLReasoner r = rf.createReasoner(ont); r.precomputeInferences(InferenceType.CLASS_ASSERTIONS); int n = r.getInstances(cls("PersonAtRisk"), false) .getFlattened().size(); System.out.printf("%-10s risk=%d %d ms%n", ad, n, System.currentTimeMillis() - t0); r.dispose(); }
HermiT risk=4 812 ms Openllet risk=4 1104 ms JFact risk=4 935 ms

Sonuçlar aynı olmalıdır — farklı çıkıyorsa ya ontoloji DL dışındadır ya da bir motor kısıtı göz ardı ediyordur.

05

SWRL + Reasoner Birlikte

Sekiz adımlı akış ve doğru sıra.

Projenin sekiz adımlı akışı

AdımİşAraç
1Ontolojiyi yükleOWL API
2Envanter raporlaOWL API
3Ön denetim: tutarlılık + boş sınıflarHermiT
4Kural motorunu kurSWRLAPI
5infer() — kuralları çalıştırDrools
6SQWRL ile raporlaSQWRL
7Son denetim: sınıflandırma + gerçeklemeHermiT
8Çıkarımı kalıcı yazOWL API

Adım 3 ve 7 aynı denetimdir — fark önemlidir: kural öncesi boş olan PersonAtRisk sonrasında dolmalıdır.

Adım 3 — Kural öncesi denetim

OWLReasoner r = new ReasonerFactory() .createReasoner(ont); System.out.println("Tutarli: " + r.isConsistent()); System.out.println("PersonAtRisk: " + r.getInstances(cls("PersonAtRisk"), false) .getFlattened()); r.dispose();
Tutarli: true PersonAtRisk: []

Boş liste beklenen sonuçtur: risk bilgisi henüz üretilmemiştir. Bu satır, sistemin çalıştığının kanıtı olacak.

Adım 4–5 — Kuralları çalıştır

SWRLRuleEngine engine = SWRLAPIFactory.createSWRLRuleEngine(ont); System.out.println("Kural: " + engine.getSWRLRules().size()); engine.infer(); // Drools ileri zincirleme
  • infer() üç işi birden yapar: aktar → çalıştır → geri yaz.
  • Protégé'deki üç düğmenin kod karşılığıdır.
  • Sonuçlar ASSERTED olarak yazılır — artık bildirilmiş bilgidir.
Kural: 7 infer() tamamlandi (812 ms) — 14 aksiyom eklendi

Adım 7 — Kural sonrası denetim

// YENI reasoner: ontoloji degisti OWLReasoner r2 = new ReasonerFactory().createReasoner(ont); for (String c : new String[]{"PersonAtRisk", "Adult", "RiskyProduct"}) System.out.println(c + " = " + r2.getInstances(cls(c), false).getFlattened());
PersonAtRisk = [TC_001, TC_002, TC_003, TC_004] Adult = [TC_001, TC_003, TC_004] RiskyProduct = [EAN_00001, EAN_00002, EAN_00003, EAN_00004]

Önemli: eski reasoner nesnesi güncellenmez. Ontoloji değiştiyse yeni reasoner oluşturun veya flush() çağırın.

Tampon sorunu: flush()

Hatalı

man.addAxiom(ont, yeniAksiyom); r.getInstances(...); // eski sonuc doner

Doğru

man.addAxiom(ont, yeniAksiyom); r.flush(); r.getInstances(...);

Reasoner varsayılan olarak tamponlu (buffering) çalışır: performans için değişiklikleri biriktirir. BufferingMode.NON_BUFFERING ile otomatik yenileme seçilebilir, ama yavaştır.

Adım 8 — Çıkarımı kalıcı yaz

List<InferredAxiomGenerator<? extends OWLAxiom>> gens = Arrays.asList(new InferredClassAssertionAxiomGenerator(), new InferredSubClassAxiomGenerator(), new InferredPropertyAssertionGenerator()); new InferredOntologyGenerator(r2, gens).fillOntology(df, ont); man.saveOntology(ont, new RDFXMLDocumentFormat(), IRI.create(new File("ALLERGY_INFERRED.owl").toURI()));

Artık PersonAtRisk(TC_001) dosyada yazılıdır. Reasoner olmayan bir istemci bile bu bilgiyi okuyabilir — materyalizasyon budur.

Hangi çıkarımı yazmalı?

GeneratorYazdığıProjede
InferredClassAssertionAxiomGeneratorBirey → sınıfGerekli (PersonAtRisk)
InferredSubClassAxiomGeneratorSınıf hiyerarşisiGerekli (RiskyProduct)
InferredPropertyAssertionGeneratorİlişki değerleriGerekli (Effected_Allergen)
InferredEquivalentClassAxiomGeneratorEşdeğerliklerİsteğe bağlı
InferredDisjointClassesAxiomGeneratorAyrıklıklarGereksiz — dosyayı şişirir

Hepsini yazmak dosyayı katbekat büyütür ve okunmaz kılar. Yalnızca tüketicinin ihtiyacı olanı yazın.

06

Hata Ayıklama ve Performans

Gerekçe üretme, tutarsızlık avı, ölçekleme.

Gerekçe üretme: neden bu sonuç?

ExplanationGenerator<OWLAxiom> eg = new InconsistentOntologyExplanationGeneratorFactory( rf, () -> 60000L) .createExplanationGenerator(ont); eg.getExplanations(soru, 3) .forEach(ex -> ex.getAxioms() .forEach(System.out::println));
TC_001 hasAllergy Lactose TC_001 ChooseProduct EAN_00004 EAN_00004 Contain Nisin Nisin Triggers Lactose S6 ⇒ Effected_Allergen S7 ⇒ PersonAtRisk

Protégé'deki Explain düğmesinin kod karşılığı. Gıda güvenliği raporlarında gerekçe göstermek yasal bir gerekliliktir.

Tutarsızlığı bulmak: örnek olay

Eklenen hatalı aksiyom

// Nisin hem katki hem alerji add(df.getOWLClassAssertionAxiom( cls("Allergy"), ind("Nisin")));

Reasoner çıktısı

isConsistent() = false Gerekce: FoodAdditives(Nisin) Allergy(Nisin) DisjointClasses(...)

Ayrıklık aksiyomu olmasaydı bu hata hiç fark edilmezdi: Nisin sessizce iki sınıfa ait olur, sorgular garipleşirdi. Aksiyomların bedeli budur — hata yakalarlar.

Performans: ne yavaşlatır?

NedenEtkiÇözüm
Her sorguda yeni reasonerBaştan sınıflandırmaTek nesne + flush()
NON_BUFFERING modHer ekleme yeniden hesapTamponlu kullan
Nitelikli sayı kısıtlarıDallanma artarGerçekten gerekliyse kullan
Çok fazla sameAsBirey birleştirme maliyetiHasKey ile sınırlı tut
Kural sayısı × birey sayısıDrools eşleme patlamasıGenel kural (S6) tercih et
r.precomputeInferences(InferenceType.CLASS_ASSERTIONS, InferenceType.CLASS_HIERARCHY);

Protégé ekranı ↔ kod eşlemesi

Reasoner  ›  HermiT 1.4.5  ›  Start reasoner
Protégé menüsüKod
Start reasonerrf.createReasoner(ont)
Synchronise reasonerr.flush()
Inferred class hierarchyr.getSubClasses(c, true)
Instances (inferred)r.getInstances(c, false)
ExplainExplanationGenerator
Export inferred axiomsInferredOntologyGenerator

Şematik gösterim. Protégé'de yaptığınız her işlemin bir kod karşılığı vardır — arayüz yalnızca API'nin bir yüzüdür.

07

Ödev ve Proje Adımı

Üç reasoner, tek rapor.

Ödev 9 — Reasoner karşılaştırması

  1. Ontolojinizi HermiT, Openllet ve JFact ile çalıştırıp süre ve sonuç karşılaştırın.
  2. Kural öncesi/sonrası PersonAtRisk farkını raporlayın.
  3. Bilinçli bir tutarsızlık ekleyip gerekçesini kodla yazdırın.
  4. Üç generator ile *_INFERRED.owl üretin; aksiyom sayısı artışını gösterin.
  5. Bir beklenen çıkarımı isEntailed ile JUnit testine dönüştürün.

Teslim

Karşılaştırma tablosu + gerekçe çıktısı + iki .owl dosyası + test sınıfı + 3 sayfa rapor.

Çözümü Hafta 10'un başında ele alacağız.

Değerlendirme ölçütleri

ÖlçütAğırlıkBeklenen
Reasoner karşılaştırması25%Üç motor, aynı sonuç, süre ölçümü
Kural öncesi/sonrası fark20%Boş → dolu gösterilmiş
Gerekçe analizi20%Aksiyom zinciri yorumlanmış
Materyalizasyon20%Generator seçimi gerekçeli
Test15%isEntailed testi geçiyor

Kaynaklar ve referanslar

  • Glimm, B., Horrocks, I., Motik, B., Stoilos, G., Wang, Z. — HermiT: An OWL 2 Reasoner, Journal of Automated Reasoning, 2014.
  • Sirin, E., Parsia, B., Grau, B.C., Kalyanpur, A., Katz, Y. — Pellet: A Practical OWL-DL Reasoner, Journal of Web Semantics, 2007.
  • Kazakov, Y., Krötzsch, M., Simančík, F. — The Incredible ELK, Journal of Automated Reasoning, 2014.
  • Tsarkov, D., Horrocks, I. — FaCT++ Description Logic Reasoner, IJCAR 2006.
  • Horridge, M., Bechhofer, S. — The OWL API, Semantic Web Journal, 2011.
  • Sarker, M.K., Krisnadhi, A., Hitzler, P. — OWLAx / ROWL: Protégé plugins, ISWC Demos.
  • Baader, F. et al. — The Description Logic Handbook, 2nd ed., Cambridge.

Özet  •  1 / 2

Çıkarım ve reasoner'lar

  • Çıkarım "olası" değil zorunlu sonuçları üretir; yöntem çelişki aramaktır.
  • Üç görev: tutarlılık, sınıflandırma, gerçekleme.
  • HermiT DL için varsayılan; Openllet SWRL ve açıklama sunar; ELK yalnızca EL profili.
  • ROWL kuralı OWL kısıtına çevirir ama aritmetik çeviremez.
  • Tutarsız ontolojide her şey doğrudur — denetim daima ilk adımdır.

Özet  •  2 / 2

API kullanımı ve sonraki adım

  • Motoru değiştirmek için tek satır yeter: fabrika.
  • Ontoloji değiştiyse flush() ya da yeni reasoner.
  • isEntailed tek soruyu sormanın en hızlı yolu.
  • Materyalizasyonda yalnızca gerekli generator'ları seçin.

Hafta 10'da

SWRL API & SQWRL: kuralları kodla yönetmek, sorgu dili, uçtan uca çalışan sistem ve proje teslimi.

Ayrıca: Ödev 9'un ayrıntılı çözümü.

Tekrar Soruları

Kendinizi sınayın

  1. Reasoner neden çelişki arar?
  2. Tutarsız ontolojide sorgu neden anlamsızdır?
  3. Unsatisfiable sınıf neye işaret eder?
  4. ELK bu projede neden uygun değil?
  1. ROWL neyi çevirebilir, neyi çeviremez?
  2. flush() unutulursa ne olur?
  3. getInstances(c, true) ile false farkı?
  4. Neden bütün generator'ları yazmamalı?

Alıştırma  •  Sınıf içi

Çıkarımı tahmin edin

Ontolojiye şu aksiyom eklenir ve HermiT çalıştırılır:

Ascorbic_Acid Triggers Lactose .

Sorular

  1. Hangi kişi için yeni Effected_Allergen üretilir?
  2. PersonAtRisk kümesi değişir mi?
  3. flush() çağırmadan sonucu görebilir misiniz?
  4. Bu çıkarım hangi kuraldan gelir: S3 mü S6 mı?

Çözüm Hafta 10'da.